# Creare il proprio dataset

<CourseFloatingBanner chapter={5}
  classNames="absolute z-10 right-0 top-0"
  notebooks={[
    {label: "Google Colab", value: "https://colab.research.google.com/github/huggingface/notebooks/blob/master/course/it/chapter5/section5.ipynb"},
    {label: "Aws Studio", value: "https://studiolab.sagemaker.aws/import/github/huggingface/notebooks/blob/master/course/it/chapter5/section5.ipynb"},
]} />

A volte il dataset che ti serve per la tua applicazione NLP non esiste, per cui dovrai crearlo da te. In questa sezione ti mostreremo come creare un corpus di [issue da GitHub](https://github.com/features/issues), usate solitamente per tenere traccia dei bug e delle feature nelle repository su GitHub. Questo corpus può essere usato in diversi modi, ad esempio:

* Esplorare il tempo impiegato per chiudere un issue, o per effettuare dei pull
* Addestrare un _classificatore multiclasse_ che assegna a ogni issue dei metadati sulla base della descrizione dell'issue (ad esempio, "bug", "enhancement", "question")
* Creare un motore di ricerca semantico per trovare quale issue corrisponde a una richiesta dell'utente

Ci focalizzeremo sulla creazione del corpus, e nella prossima sezione affronteremo la creazione di un motore di ricerca semantico. Useremo gli issue GitHub associate a un progetto open source molto popolare: 🤗 Datasets! Diamo un'occhiata a come recuperare i dati e come esplorare le informazioni contenute negli issue. 

## Recuperare i dati 

Puoi trovare tutte gli issue in 🤗 Datasets navigando nella [sezione Issues della repository](https://github.com/huggingface/datasets/issues). Come si vede dallo screenshot, al momento della scrittura c'erano 331 issue aperti e 668 issue chiusi.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-issues.png" alt="The GitHub issues associated with 🤗 Datasets." width="80%"/>
</div>

Se clicchi su una di questi issue vedrai che contiene un titolo, una descrizione, e un set di etichette che caratterizzano l'issue. Un esempio è mostrato nello screenshot successivo.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-issues-single.png" alt="A typical GitHub issue in the 🤗 Datasets repository." width="80%"/>
</div>

Per scaricare gli issue della repository, useremo la [REST API di GitHub](https://docs.github.com/en/rest) per interrogare l'[endpoint `Issues`](https://docs.github.com/en/rest/reference/issues#list-repository-issues). Questo endpoint restituisce una lista di oggetti JSON, e ogni oggetto contiene un gran numero di campi, tra cui il titolo e la descrizione, così come dei metadati circo lo status dell'issue e altro ancora. 

Una maniera conveniente di scaricare gli issue è attraverso la libreria `requests`, che rappresenta il metodo standard di fare richieste HTTP su Python. Puoi installa la libreria attraverso il codice:

```python
!pip install requests
```

Una volta che la libreria è stata installata, puoi effettuare una richiesta GET all'endpoint `Issues` utilizzando la funzione `requests.get()`. Ad esempio, puoi eseguire il comando mostrato di seguito per recuperare il primo issue nella prima pagina:

```py
import requests

url = "https://api.github.com/repos/huggingface/datasets/issues?page=1&per_page=1"
response = requests.get(url)
```

L'oggetto `response` contiene un sacco di informazioni utili sulla richiesta, compreso il codice di stato HTTP:

```py
response.status_code
```

```python out
200
```

Lo status `200` indica che la richiesta ha avuto buon fine (puoi trovare una lista di codici di stato HTTTP [qui](https://it.wikipedia.org/wiki/Codici_di_stato_HTTP)). Ma ciò che ci interessa davvero è il _payload_, a cui è possibile accedere utilizzando diversi formati come byte, stringh, o JSON. Visto che sappiamo che i nostri issue sono in formato JSON, diamo un'occhiata al payload come segue:

```py
response.json()
```

```python out
[{'url': 'https://api.github.com/repos/huggingface/datasets/issues/2792',
  'repository_url': 'https://api.github.com/repos/huggingface/datasets',
  'labels_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792/labels{/name}',
  'comments_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792/comments',
  'events_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792/events',
  'html_url': 'https://github.com/huggingface/datasets/pull/2792',
  'id': 968650274,
  'node_id': 'MDExOlB1bGxSZXF1ZXN0NzEwNzUyMjc0',
  'number': 2792,
  'title': 'Update GooAQ',
  'user': {'login': 'bhavitvyamalik',
   'id': 19718818,
   'node_id': 'MDQ6VXNlcjE5NzE4ODE4',
   'avatar_url': 'https://avatars.githubusercontent.com/u/19718818?v=4',
   'gravatar_id': '',
   'url': 'https://api.github.com/users/bhavitvyamalik',
   'html_url': 'https://github.com/bhavitvyamalik',
   'followers_url': 'https://api.github.com/users/bhavitvyamalik/followers',
   'following_url': 'https://api.github.com/users/bhavitvyamalik/following{/other_user}',
   'gists_url': 'https://api.github.com/users/bhavitvyamalik/gists{/gist_id}',
   'starred_url': 'https://api.github.com/users/bhavitvyamalik/starred{/owner}{/repo}',
   'subscriptions_url': 'https://api.github.com/users/bhavitvyamalik/subscriptions',
   'organizations_url': 'https://api.github.com/users/bhavitvyamalik/orgs',
   'repos_url': 'https://api.github.com/users/bhavitvyamalik/repos',
   'events_url': 'https://api.github.com/users/bhavitvyamalik/events{/privacy}',
   'received_events_url': 'https://api.github.com/users/bhavitvyamalik/received_events',
   'type': 'User',
   'site_admin': False},
  'labels': [],
  'state': 'open',
  'locked': False,
  'assignee': None,
  'assignees': [],
  'milestone': None,
  'comments': 1,
  'created_at': '2021-08-12T11:40:18Z',
  'updated_at': '2021-08-12T12:31:17Z',
  'closed_at': None,
  'author_association': 'CONTRIBUTOR',
  'active_lock_reason': None,
  'pull_request': {'url': 'https://api.github.com/repos/huggingface/datasets/pulls/2792',
   'html_url': 'https://github.com/huggingface/datasets/pull/2792',
   'diff_url': 'https://github.com/huggingface/datasets/pull/2792.diff',
   'patch_url': 'https://github.com/huggingface/datasets/pull/2792.patch'},
  'body': '[GooAQ](https://github.com/allenai/gooaq) dataset was recently updated after splits were added for the same. This PR contains new updated GooAQ with train/val/test splits and updated README as well.',
  'performed_via_github_app': None}]
```

Wow, quante informazioni! Possiamo vedere alcuni campi utili come `title`, `body` e `number` che descrivono l'issue, così come informazioni sull'utente che l'ha aperto.

<Tip>

✏️ **Prova tu!** Clicca su alcuni degli URL nel payload JSON per farti un'idea del tipo di informazione a cui è collegato ogni issue GitHub.

</Tip>

Come descritto nella [documentazione di GitHub](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting), le richieste senza autenticazione sono limitate a 60 ogni ora. Benché possiamo aumentare il parametro della query `per_page` per ridurre il numero di richieste, raggiungerai comunque il limite su qualunque repository che ha qualche migliaio di issue. Quindi, dovresti seguire le [istruzioni](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) su come creare un _token di accesso personale_ così che puoi aumentare il limite a 5.000 richieste ogni ora. Una volta che hai ottenuto il tuo token, puoi includerlo come parte dell'header della richiesta:

```py
GITHUB_TOKEN = xxx  # inserisci qui il tuo token GitHub
headers = {"Authorization": f"token {GITHUB_TOKEN}"}
```

<Tip warning={true}>

⚠️ Fai attenzione a non condividere un notebook con il tuo `GITHUB_TOKEN` al suo interno. Ti consigliamo di cancellare l'ultima cella una volta che l'hai eseguita per evitare di far trapelare quest'informazione accidentalmente. Meglio ancora, salva il tuo token in un file *.env* e usa la [libreria `python-dotenv`](https://github.com/theskumar/python-dotenv) per caricarlo automaticamente come una variabile d'ambiente.

</Tip>

Ora che abbiamo il nostro token di accesso, creiamo una funzione che scarichi tutti gli issue da una repository GitHub:

```py
import time
import math
from pathlib import Path
import pandas as pd
from tqdm.notebook import tqdm


def fetch_issues(
    owner="huggingface",
    repo="datasets",
    num_issues=10_000,
    rate_limit=5_000,
    issues_path=Path("."),
):
    if not issues_path.is_dir():
        issues_path.mkdir(exist_ok=True)

    batch = []
    all_issues = []
    per_page = 100  # Numero di issue da restituire per pagina
    num_pages = math.ceil(num_issues / per_page)
    base_url = "https://api.github.com/repos"

    for page in tqdm(range(num_pages)):
        # La query ha state=all per ottenere sia gli issue aperti che quelli chiusi
        query = f"issues?page={page}&per_page={per_page}&state=all"
        issues = requests.get(f"{base_url}/{owner}/{repo}/{query}", headers=headers)
        batch.extend(issues.json())

        if len(batch) > rate_limit and len(all_issues) < num_issues:
            all_issues.extend(batch)
            batch = []  # puliamo la batch per il termine successivo
            print(f"Reached GitHub rate limit. Sleeping for one hour ...")
            time.sleep(60 * 60 + 1)

    all_issues.extend(batch)
    df = pd.DataFrame.from_records(all_issues)
    df.to_json(f"{issues_path}/{repo}-issues.jsonl", orient="records", lines=True)
    print(
        f"Downloaded all the issues for {repo}! Dataset stored at {issues_path}/{repo}-issues.jsonl"
    )
```

Ora quando eseguiremo `fetch_issues()`, scaricherà tutti gli issue in batch per evitare di superare il limite di GitHub del numero di richieste per ora; il risultato sarà conservato in un file _repository_name-issues.jsonl_, in cui ogni linea è un oggetto JSON che rappresenta un issue. Usiamo questa funzione per recuperare tutti gli issue da 🤗 Datasets:

```py
# A seconda della tua connessione internet, ci potrebbe volere qualche secondo...
fetch_issues()
```

Una volta che gli issue sono stati scaricati, possiamo caricarli in locale usando le nuove abilità imparate nella [sezione 2](/course/chapter5/2):

```py
issues_dataset = load_dataset("json", data_files="datasets-issues.jsonl", split="train")
issues_dataset
```

```python out
Dataset({
    features: ['url', 'repository_url', 'labels_url', 'comments_url', 'events_url', 'html_url', 'id', 'node_id', 'number', 'title', 'user', 'labels', 'state', 'locked', 'assignee', 'assignees', 'milestone', 'comments', 'created_at', 'updated_at', 'closed_at', 'author_association', 'active_lock_reason', 'pull_request', 'body', 'timeline_url', 'performed_via_github_app'],
    num_rows: 3019
})
```

Benissimo, abbiamo creato il nostro primo dataset da zero! Ma perché ci sono migliaia di issue quando la [sezione Issues](https://github.com/huggingface/datasets/issues) della repository 🤗 Datasets mostra circa 1,000 issue in totale 🤔? Come indicato nella [documentazione di GitHub](https://docs.github.com/en/rest/reference/issues#list-issues-assigned-to-the-authenticated-user), è perché abbiamo scaricato anche le richieste di pull:

> GitHub's REST API v3 considers every pull request an issue, but not every issue is a pull request. For this reason, "Issues" endpoints may return both issues and pull requests in the response. You can identify pull requests by the `pull_request` key. Be aware that the `id` of a pull request returned from "Issues" endpoints will be an issue id.

(_La REST API v3 di GitHub considera ogni richiesta di pull un issue, ma non ogni issue è una richiesta di pull. Per questa ragione, gli endpoint "Issues" potrebbe tornare sia gli issue che le richieste di pull. È possibile identificare le richieste di pull utilizzando la chiave `pull_request`. Tieni presente che l'`id` di una richiesta di pull resituita dagli endpoint `Issues` sarà un id di un issue._)

Poichè i contenuti degli issue e delle richieste di pull sono molto diversi, facciamo un po' di preprocessing per permetterci di distinguere tra i due.

## Pulire i dati

Il frammento precedente della documentazione di GitHub ci dice che la colonna `pull_request` può essere utilizzata per distinguere gli issue e le richieste di pull. Diamo uno sguardo a un esempio casuale per vedere qual è la differenza. Come abbiamo fatto nella [sezione 3](/course/chapter5/3), concateneremo `Dataset.shuffle()` e `Dataset.select()` per creare un campione random, e poi zipperemo le colonne `html_url` e `pull_request` così da poter paragonare i diversi URL:

```py
sample = issues_dataset.shuffle(seed=666).select(range(3))

# Stampiamo le entrate `URL` e `pull_request`
for url, pr in zip(sample["html_url"], sample["pull_request"]):
    print(f">> URL: {url}")
    print(f">> Pull request: {pr}\n")
```

```python out
>> URL: https://github.com/huggingface/datasets/pull/850
>> Pull request: {'url': 'https://api.github.com/repos/huggingface/datasets/pulls/850', 'html_url': 'https://github.com/huggingface/datasets/pull/850', 'diff_url': 'https://github.com/huggingface/datasets/pull/850.diff', 'patch_url': 'https://github.com/huggingface/datasets/pull/850.patch'}

>> URL: https://github.com/huggingface/datasets/issues/2773
>> Pull request: None

>> URL: https://github.com/huggingface/datasets/pull/783
>> Pull request: {'url': 'https://api.github.com/repos/huggingface/datasets/pulls/783', 'html_url': 'https://github.com/huggingface/datasets/pull/783', 'diff_url': 'https://github.com/huggingface/datasets/pull/783.diff', 'patch_url': 'https://github.com/huggingface/datasets/pull/783.patch'}
```

Possiamo vedere che ogni richiesta di pull è associata a diversi URL, mentre i comuni issue hanno un'entrata `None`. Possiamo usare questa distinzione per crare una nuova colonna `is_pull_request` che controlla se il campo `pull_request` sia `None` o meno:

```py
issues_dataset = issues_dataset.map(
    lambda x: {"is_pull_request": False if x["pull_request"] is None else True}
)
```

<Tip>

✏️ **Prova tu!** Calcola il tempo medio che ci vuole a chiudere un issue su 🤗 Datasets. Potrebbe essere utile usare la funzione `Dataset.filter()` per eliminare le richieste di pull e gli issue aperti, e puoi usare la funzione `Dataset.set_format()` per convertire il dataset in un `DataFrame` così che puoi facilmente manipolare i timestamp `created_at` e `closed_at`. Per dei punti bonus, calcola il tempo medio che ci vuole a chiudere le richieste di pull.

</Tip>

Benché potremmo procedere e pulire ulteriormente il dataset eliminando o rinominando alcune colonne, è solitamente buona prassi lasciare il dataset quando più intatto è possibile in questo stadio, così che può essere utilizzato facilmente in più applicazioni.

Prima di caricare il nostro dataset sull'Hub Hugging Face, dobbiamo occuparci di una cosa che manca: i commenti associati a ogni issue e richiesta di pull. Hai indovinato, li aggiungeremo utilizzando la REST API di GitHub!

## Estendere il dataset 

Come mostrato negli screenshot di seguito, i commenti associati a un issue o una richiesta di pull offrono una fonte molto ricca di informazioni, soprattutto se siamo interessati a costruire un motore di ricerca per rispondere alle richieste degli utenti sulla libreria.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-issues-comment.png" alt="Comments associated with an issue about 🤗 Datasets." width="80%"/>
</div>

La REST API di GitHub offre un [endpoint `Comments`](https://docs.github.com/en/rest/reference/issues#list-issue-comments) che restituisce tutti i commenti associati con un numero di issue. Testiamo quest'endpoint per vedere cosa restituisce:

```py
issue_number = 2792
url = f"https://api.github.com/repos/huggingface/datasets/issues/{issue_number}/comments"
response = requests.get(url, headers=headers)
response.json()
```

```python out
[{'url': 'https://api.github.com/repos/huggingface/datasets/issues/comments/897594128',
  'html_url': 'https://github.com/huggingface/datasets/pull/2792#issuecomment-897594128',
  'issue_url': 'https://api.github.com/repos/huggingface/datasets/issues/2792',
  'id': 897594128,
  'node_id': 'IC_kwDODunzps41gDMQ',
  'user': {'login': 'bhavitvyamalik',
   'id': 19718818,
   'node_id': 'MDQ6VXNlcjE5NzE4ODE4',
   'avatar_url': 'https://avatars.githubusercontent.com/u/19718818?v=4',
   'gravatar_id': '',
   'url': 'https://api.github.com/users/bhavitvyamalik',
   'html_url': 'https://github.com/bhavitvyamalik',
   'followers_url': 'https://api.github.com/users/bhavitvyamalik/followers',
   'following_url': 'https://api.github.com/users/bhavitvyamalik/following{/other_user}',
   'gists_url': 'https://api.github.com/users/bhavitvyamalik/gists{/gist_id}',
   'starred_url': 'https://api.github.com/users/bhavitvyamalik/starred{/owner}{/repo}',
   'subscriptions_url': 'https://api.github.com/users/bhavitvyamalik/subscriptions',
   'organizations_url': 'https://api.github.com/users/bhavitvyamalik/orgs',
   'repos_url': 'https://api.github.com/users/bhavitvyamalik/repos',
   'events_url': 'https://api.github.com/users/bhavitvyamalik/events{/privacy}',
   'received_events_url': 'https://api.github.com/users/bhavitvyamalik/received_events',
   'type': 'User',
   'site_admin': False},
  'created_at': '2021-08-12T12:21:52Z',
  'updated_at': '2021-08-12T12:31:17Z',
  'author_association': 'CONTRIBUTOR',
  'body': "@albertvillanova my tests are failing here:\r\n```\r\ndataset_name = 'gooaq'\r\n\r\n    def test_load_dataset(self, dataset_name):\r\n        configs = self.dataset_tester.load_all_configs(dataset_name, is_local=True)[:1]\r\n>       self.dataset_tester.check_load_dataset(dataset_name, configs, is_local=True, use_local_dummy_data=True)\r\n\r\ntests/test_dataset_common.py:234: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\ntests/test_dataset_common.py:187: in check_load_dataset\r\n    self.parent.assertTrue(len(dataset[split]) > 0)\r\nE   AssertionError: False is not true\r\n```\r\nWhen I try loading dataset on local machine it works fine. Any suggestions on how can I avoid this error?",
  'performed_via_github_app': None}]
```

Possiamo vedere che il commento è archiviato nel campo `body`, quindi possiamo scvrivere una semplice funzione che restituisce tutti i commenti associati con un issue estraendo i contenuti di `body` per ogni elemento in `response.json()`:

```py
def get_comments(issue_number):
    url = f"https://api.github.com/repos/huggingface/datasets/issues/{issue_number}/comments"
    response = requests.get(url, headers=headers)
    return [r["body"] for r in response.json()]


# Testiamo la nostra funzione
get_comments(2792)
```

```python out
["@albertvillanova my tests are failing here:\r\n```\r\ndataset_name = 'gooaq'\r\n\r\n    def test_load_dataset(self, dataset_name):\r\n        configs = self.dataset_tester.load_all_configs(dataset_name, is_local=True)[:1]\r\n>       self.dataset_tester.check_load_dataset(dataset_name, configs, is_local=True, use_local_dummy_data=True)\r\n\r\ntests/test_dataset_common.py:234: \r\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \r\ntests/test_dataset_common.py:187: in check_load_dataset\r\n    self.parent.assertTrue(len(dataset[split]) > 0)\r\nE   AssertionError: False is not true\r\n```\r\nWhen I try loading dataset on local machine it works fine. Any suggestions on how can I avoid this error?"]
```

Sembra andar bene, quindi possiamo usare `Dataset.map()` per aggiungere una nuova colonna `comments` a ogni usse nel nostro dataset:

```py
# A seconda della tua connessione, potrebbe volerci qualche secondo...
issues_with_comments_dataset = issues_dataset.map(
    lambda x: {"comments": get_comments(x["number"])}
)
```

Come passaggio finale, salviamo il dataset esteso assieme ai nostri dati non processati, così da poter caricare entrambi sull'Hub:

```py
issues_with_comments_dataset.to_json("issues-datasets-with-comments.jsonl")
```

## Caricare il dataset sull'Hub Hugging Face 

<Youtube id="HaN6qCr_Afc"/>

Ora che abbiamo il nostro dataset esteso, è arrivato il momento di caricarlo sull'Hub, così da poterlo condividere con la community! Per caricare il dataset useremo la [libreria 🤗 Hub](https://github.com/huggingface/huggingface_hub), che ci permette di interagire con l'Hub di Hugging Face attraverso un'API di Python. 🤗 Hub è preinstallato con 🤗 Transformers, così possiamo usarlo da subito. Ad esempio, possiamo usare la funzione `list_datastes()` per avere informazioni su tutti i dataset pubblici attualmente presenti sull'Hub:

```py
from huggingface_hub import list_datasets

all_datasets = list_datasets()
print(f"Number of datasets on Hub: {len(all_datasets)}")
print(all_datasets[0])
```

```python out
Number of datasets on Hub: 1487
Dataset Name: acronym_identification, Tags: ['annotations_creators:expert-generated', 'language_creators:found', 'languages:en', 'licenses:mit', 'multilinguality:monolingual', 'size_categories:10K<n<100K', 'source_datasets:original', 'task_categories:structure-prediction', 'task_ids:structure-prediction-other-acronym-identification']
```

Possiamo vedere che al momento ci sono circa 1.500 dataset sull'Hub, e la funzione `list_datasets()` inoltre permette di avere alcuni metadati su ciascuna repository.

Per ciò che ci riguarda, la prima cosa che dobbiamo fare è crare una nuova repository nell'Hub. Per far ciò abbiamo bisogno di un token di autentificazione, che pouò essere ottenuto effettuando l'accesso nell'Hub Hugging Face con la funzione `notebook_login()`:

```py
from huggingface_hub import notebook_login

notebook_login()
```

Questo creerà un widget in cui puoi inserire il tuo username e la tua password, e un token API verrà salvato in *~/.huggingface/token*. Se stai eseguendo il codice in un terminale, puoi effettuare l'accesso attraverso il comando:

```bash
huggingface-cli login
```

Una volta fatto questo, possiamo crare una nuova repository con la funzione `create_repo()`:

```py
from huggingface_hub import create_repo

repo_url = create_repo(name="github-issues", repo_type="dataset")
repo_url
```

```python out
'https://huggingface.co/datasets/lewtun/github-issues'
```

In quest'esempio, abbiamo creato una repository vuota chiamata `github-issues` con l'username `lewtun` (l'username dovrebbe essere quello del tuo account Hub quando esegui questo codice!).

<Tip>

✏️ **Prova tu!** Usa le tue credenziali dell'Hub Hugging Face per ottenere un token e creare una repository vuota chiamata `github-issues`. Ricordati di **non salvere mai le tue credenziali** su Colab o qualunque altra repository, perché potrebbero essere recuperate da malintenzionati.

</Tip>

Ora, cloniamo la repository dall'Hub alla nostra macchina e copiamo al suo interno i file del nostro dataset. 🤗 Hub contiene una classe `Repository` che ha al suo interno molti dei comandi più comuni di Git, per cui per clonare la repository in remoto dobbiamo semplicemente fornire l'URL e il percorso locale in cui desideriamo clonare:

```py
from huggingface_hub import Repository

repo = Repository(local_dir="github-issues", clone_from=repo_url)
!cp issues-datasets-with-comments.jsonl github-issues/
```

Di default, diverse estensioni file (ad esempio *.bin*, *.gz* e *.zip*) sono registrate da Git LFS, così che i file di grandi dimensioni possono essere gestiti all'interno dello stesso workflow. Puoi trovare una lista delle estensioni di file monitorati nel file *.gitattributes* della repository. Per includere il formato JSON Lines a questa lista, possiamo utilizzare il comando:

```py
repo.lfs_track("*.jsonl")
```

Ora possiamo usare `Repository.push_to_hub()` per caricare il dataset sull'Hub:

```py
repo.push_to_hub()
```

Se navighiamo fino all'URL contenuto in `repo_url`, vedremo che il file del nostro dataset è stato caricato.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/hub-repo.png" alt="Our dataset repository on the Hugging Face Hub." width="80%"/>
</div>

Da qui, chiunque può scaricare il dataset semplicemente inserendo l'ID della repository come argomento `path` di `load_dataset()`:

```py
remote_dataset = load_dataset("lewtun/github-issues", split="train")
remote_dataset
```

```python out
Dataset({
    features: ['url', 'repository_url', 'labels_url', 'comments_url', 'events_url', 'html_url', 'id', 'node_id', 'number', 'title', 'user', 'labels', 'state', 'locked', 'assignee', 'assignees', 'milestone', 'comments', 'created_at', 'updated_at', 'closed_at', 'author_association', 'active_lock_reason', 'pull_request', 'body', 'performed_via_github_app', 'is_pull_request'],
    num_rows: 2855
})
```

Bene, abbiamo caricato il nostro dataset sull'Hub, e può essere utilizzato da tutti! C'è un'altra cosa importante che dobbiamo fare: aggiungere una _dataset card_ che spiega come è stato creato il corpus, e offre altre informazioni utili per la community.

<Tip>

💡 Puoi caricare un dataset nell'Hub di Hugging Face anche direttamente dal terminale usando `huggingface-cli` e un po' di magia Git. La [guida a 🤗 Datasets](https://huggingface.co/docs/datasets/share#share-a-dataset-using-the-cli) spiega come farlo. 

</Tip>

## Creare una dataset card

I dataset ben-documentati sono più utili agli altri utenti (compreso il futuro te!), poiché spiegano il contesto per permettere agli utenti di decidere se un dataset può essere utile, e valutare gli eventuali bias o rischi associati nell'utilizzo del dataset.

Sull'Hug di Hugging Face, queste informazioni si trovano nel file *README.md* della repository. Ci sono due passaggi principali che dovresti seguire prima di creare questo file:

1. Usa l'[applicatione `datasets-tagging`](https://huggingface.co/datasets/tagging/) per creare tag di metadati in formato YAML. Questi tag sono usato per una serie di funzioni di ricerca sull'Hub di Hugging Face, e assicurano che il tuo dataset possa essere facilmente trovato dai membri della community. Poichè abbiamo creato un nostro dataset, dovrai clonare la repository `datasets-tagging`, ed eseguire l'applicazione in locale. Ecco com'è l'interfaccia:

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/datasets-tagger.png" alt="The `datasets-tagging` interface." width="80%"/>
</div>

2. Leggi la [guida 🤗 Datasets](https://github.com/huggingface/datasets/blob/master/templates/README_guide.md) sulla creazione di dataset card informative, e usala come template.

Puoi creare il file *README.md* direttamente sull'Hub, e puoi trovare un modello per una dataset card nella repository `lewtun/github-issues`. Di seguito è mostrato uno screenshot di una dataset card già compilata.

<div class="flex justify-center">
<img src="https://huggingface.co/datasets/huggingface-course/documentation-images/resolve/main/en/chapter5/dataset-card.png" alt="A dataset card." width="80%"/>
</div>

<Tip>

✏️ **Prova tu!** Usa l'applicazione `dataset-tagging` e la [guida 🤗 Datasets](https://github.com/huggingface/datasets/blob/master/templates/README_guide.md) per completare il file *README.md* per il tuo dataset di issue di GitHub.
</Tip>

È tutto! Abbiamo visto in questa sezione che creare un buon dataset può essere un'impresa, ma per fortuna caricarlo e condividerlo con la community è molto più semplice. Nella prossima sezione useremo il nostro nuovo dataset per creare un motore di ricerca semantico con 🤗 Datasets, che abbina alle domande gli issue e i commenti più rilevanti.

<Tip>

✏️ **Prova tu!** Segui i passi che abbiamo eseguito in questa sezione per creare un dataset di issue GitHub per la tua libreria open source preferita (ovviamente scegli qualcosa di diverso da 🤗 Datasets!). Per punti bonus, esegui il fine-tuning di un classificatore multiclasse per predirre i tag presenti nel campo `labels`.

</Tip>


